Micron Document
welo git mirrors

Node / public / reticulum / commits / dfb5af5

Commit dfb5af5dd1ac8276e6d7ecd8b2cc58172f5bffcc


Parents : 3f1e2bc
Author : Mark Qvist <mark@unsigned.io>
Date : 2021-05-16T23:14:49+02:00

Added docstrings, refactored method names.

Changes

4 files changed, 168 insertions(+), 26 deletions(-)

M RNS/Link.py +79 -6
M RNS/Packet.py +64 -16

Diff

diff --git a/RNS/Identity.py b/RNS/Identity.py
index 03a015051..cda5b8843 100644
--- a/RNS/Identity.py
+++ b/RNS/Identity.py
@@ -161,7 +161,7 @@ class Identity:
announced_identity.load_public_key(public_key)
if announced_identity.pub != None and announced_identity.validate(signature, signed_data):
- RNS.Identity.remember(packet.getHash(), destination_hash, public_key, app_data)
+ RNS.Identity.remember(packet.get_hash(), destination_hash, public_key, app_data)
RNS.log("Stored valid announce from "+RNS.prettyhexrep(destination_hash), RNS.LOG_DEBUG)
del announced_identity
return True

diff --git a/RNS/Link.py b/RNS/Link.py
index d135b2694..95fc56916 100644
--- a/RNS/Link.py
+++ b/RNS/Link.py
@@ -19,11 +19,23 @@ class LinkCallbacks:
self.link_established = None
self.link_closed = None
self.packet = None
+ self.resource = None
self.resource_started = None
self.resource_concluded = None
class Link:
+ """
+ This class.
+
+ :param destination: A :ref:`RNS.Destination<api-destination>` instance which to establish a link to.
+ :param owner: Internal use by :ref:`RNS.Transport<api-Transport>`, ignore this argument.
+ :param peer_pub_bytes: Internal use by :ref:`RNS.Transport<api-Transport>`, ignore this argument.
+ """
CURVE = ec.SECP256R1()
+ """
+ The curve used for Elliptic Curve DH key exchanges
+ """
+
ECPUBSIZE = 91
BLOCKSIZE = 16
AES_HMAC_OVERHEAD = 58
@@ -33,9 +45,15 @@ class Link:
# but calculated from something like
# first-hop RTT latency and distance
DEFAULT_TIMEOUT = 15.0
+ """
+ Default timeout for link establishment in seconds.
+ """
TIMEOUT_FACTOR = 3
STALE_GRACE = 2
KEEPALIVE = 180
+ """
+ Interval for sending keep-alive packets on established links in seconds.
+ """
PENDING = 0x00
HANDSHAKE = 0x01
@@ -243,18 +261,31 @@ class Link:
return None
def no_inbound_for(self):
+ """
+ :returns: The time in seconds since last inbound packet on the link.
+ """
return time.time() - self.last_inbound
def no_outbound_for(self):
+ """
+ :returns: The time in seconds since last outbound packet on the link.
+ """
return time.time() - self.last_outbound
def inactive_for(self):
+ """
+ :returns: The time in seconds since activity on the link.
+ """
return min(self.no_inbound_for(), self.no_outbound_for())
def had_outbound(self):
self.last_outbound = time.time()
def teardown(self):
+ """
+ Closes the link and purges encryption keys. New keys will
+ be used if a new link to the same destination is established.
+ """
if self.status != Link.PENDING and self.status != Link.CLOSED:
teardown_packet = RNS.Packet(self, self.link_id, context=RNS.Packet.LINKCLOSE)
teardown_packet.send()
@@ -398,9 +429,8 @@ class Link:
pass
elif self.resource_strategy == Link.ACCEPT_APP:
if self.callbacks.resource != None:
- thread = threading.Thread(target=self.callbacks.resource, args=(packet))
- thread.setDaemon(True)
- thread.start()
+ if self.callbacks.resource(resource):
+ RNS.Resource.accept(packet, self.callbacks.resource_concluded)
elif self.resource_strategy == Link.ACCEPT_ALL:
RNS.Resource.accept(packet, self.callbacks.resource_concluded)
@@ -496,14 +526,41 @@ class Link:
self.callbacks.link_closed = callback
def packet_callback(self, callback):
+ """
+ Registers a function to be called when a packet has been
+ received over this link.
+
+ :param callback: A function or method with the signature *callback(message, packet)* to be called.
+ """
self.callbacks.packet = callback
- # Called when an incoming resource transfer is started
+ def resource_callback(self, callback):
+ """
+ Registers a function to be called when a resource has been
+ advertised over this link. If the function returns *True*
+ the resource will be accepted. If it returns *False* it will
+ be ignored.
+
+ :param callback: A function or method with the signature *callback(resource)* to be called.
+ """
+ self.callbacks.resource = callback
+
def resource_started_callback(self, callback):
+ """
+ Registers a function to be called when a resource has begun
+ transferring over this link.
+
+ :param callback: A function or method with the signature *callback(resource)* to be called.
+ """
self.callbacks.resource_started = callback
- # Called when a resource transfer is concluded
def resource_concluded_callback(self, callback):
+ """
+ Registers a function to be called when a resource has concluded
+ transferring over this link.
+
+ :param callback: A function or method with the signature *callback(resource)* to be called.
+ """
self.callbacks.resource_concluded = callback
def resource_concluded(self, resource):
@@ -513,6 +570,12 @@ class Link:
self.outgoing_resources.remove(resource)
def set_resource_strategy(self, resource_strategy):
+ """
+ Sets the resource strategy for the link.
+
+ :param resource_strategy: One of ``RNS.Link.ACCEPT_NONE``, ``RNS.Link.ACCEPT_ALL`` or ``RNS.Link.ACCEPT_APP``. If ``RNS.Link.ACCEPT_APP`` is set, the `resource_callback` will be called to determine whether the resource should be accepted or not.
+ :raises: *TypeError* if the resource strategy is unsupported.
+ """
if not resource_strategy in Link.resource_strategies:
raise TypeError("Unsupported resource strategy")
else:
@@ -542,7 +605,17 @@ class Link:
else:
return True
- def disableEncryption(self):
+ def disable_encryption(self):
+ """
+ HAZARDOUS. This will downgrade the link to encryptionless. All
+ information over the link will be sent in plaintext. Never use
+ this in production applications. Should only be used for debugging
+ purposes, and will disappear in a future version.
+
+ If encryptionless links are not explicitly allowed in the users
+ configuration file, Reticulum will terminate itself along with the
+ client application and throw an error message to the user.
+ """
if (RNS.Reticulum.should_allow_unencrypted()):
RNS.log("The link "+str(self)+" was downgraded to an encryptionless link", RNS.LOG_NOTICE)
self.__encryption_disabled = True

diff --git a/RNS/Packet.py b/RNS/Packet.py
index f4dd4ba1e..6283cfe35 100755
--- a/RNS/Packet.py
+++ b/RNS/Packet.py
@@ -5,6 +5,20 @@ import time
import RNS
class Packet:
+ """
+ The Packet class is used to create packet instances that can be
+ sent over a Reticulum network.
+
+ :param destination: A :ref:`RNS.Destination<api-destination>` instance to which the packet will be sent.
+ :param data: The data payload to be included in the packet as *bytes*.
+ :param create_receipt: Specifies whether a :ref:`RNS.PacketReceipt<api-packetreceipt>` should be created when instantiating the packet.
+ :param type: Internal use by :ref:`RNS.Transport<api-transport>`. Defaults to ``RNS.Packet.DATA``, and should not be specified.
+ :param context: Internal use by :ref:`RNS.Transport<api-transport>`. Ignore.
+ :param transport_type: Internal use by :ref:`RNS.Transport<api-transport>`. Ignore.
+ :param transport_id: Internal use by :ref:`RNS.Transport<api-transport>`. Ignore.
+ :param attached_interface: Internal use by :ref:`RNS.Transport<api-transport>`. Ignore.
+ """
+
# Packet types
DATA = 0x00 # Data packets
ANNOUNCE = 0x01 # Announces
@@ -155,7 +169,7 @@ class Packet:
raise IOError("Packet size of "+str(len(self.raw))+" exceeds MTU of "+str(self.MTU)+" bytes")
self.packed = True
- self.updateHash()
+ self.update_hash()
def unpack(self):
self.flags = self.raw[0]
@@ -178,12 +192,14 @@ class Packet:
self.data = self.raw[13:]
self.packed = False
- self.updateHash()
+ self.update_hash()
- # Sends the packet. Returns a receipt if one is generated,
- # or None if no receipt is available. Returns False if the
- # packet could not be sent.
def send(self):
+ """
+ Sends the packet.
+
+ :returns: A :ref:`RNS.PacketReceipt<api-packetreceipt>` instance if *create_receipt* was set to *True* when the packet was instantiated, if not returns *None*. If the packet could not be sent *False* is returned.
+ """
if not self.sent:
if self.destination.type == RNS.Destination.LINK:
if self.destination.status == RNS.Link.CLOSED:
@@ -208,6 +224,11 @@ class Packet:
raise IOError("Packet was already sent")
def resend(self):
+ """
+ Re-sends the packet.
+
+ :returns: A :ref:`RNS.PacketReceipt<api-packetreceipt>` instance if *create_receipt* was set to *True* when the packet was instantiated, if not returns *None*. If the packet could not be sent *False* is returned.
+ """
if self.sent:
if RNS.Transport.outbound(self):
return self.receipt
@@ -239,16 +260,16 @@ class Packet:
def validate_proof(self, proof):
return self.receipt.validate_proof(proof)
- def updateHash(self):
- self.packet_hash = self.getHash()
+ def update_hash(self):
+ self.packet_hash = self.get_hash()
- def getHash(self):
- return RNS.Identity.full_hash(self.getHashablePart())
+ def get_hash(self):
+ return RNS.Identity.full_hash(self.get_hashable_part())
def getTruncatedHash(self):
- return RNS.Identity.truncated_hash(self.getHashablePart())
+ return RNS.Identity.truncated_hash(self.get_hashable_part())
- def getHashablePart(self):
+ def get_hashable_part(self):
hashable_part = bytes([self.raw[0] & 0b00001111])
if self.header_type == Packet.HEADER_2:
hashable_part += self.raw[12:]
@@ -259,7 +280,7 @@ class Packet:
class ProofDestination:
def __init__(self, packet):
- self.hash = packet.getHash()[:10];
+ self.hash = packet.get_hash()[:10];
self.type = RNS.Destination.SINGLE
def encrypt(self, plaintext):
@@ -267,6 +288,12 @@ class ProofDestination:
class PacketReceipt:
+ """
+ The PacketReceipt class is used to receive notifications about
+ :ref:`RNS.Packet<api-packet>` instances sent over the network. Instances
+ of this class should never be created manually, but always returned
+ from a the *send()* method of a :ref:`RNS.Packet<api-packet>` instance.
+ """
# Receipt status constants
FAILED = 0x00
SENT = 0x01
@@ -279,7 +306,7 @@ class PacketReceipt:
# Creates a new packet receipt from a sent packet
def __init__(self, packet):
- self.hash = packet.getHash()
+ self.hash = packet.get_hash()
self.sent = True
self.sent_at = time.time()
self.timeout = Packet.TIMEOUT
@@ -289,6 +316,12 @@ class PacketReceipt:
self.callbacks = PacketReceiptCallbacks()
self.concluded_at = None
+ def get_status(self):
+ """
+ :returns: The status of the associated :ref:`RNS.Packet<api-packet>` instance. Can be one of ``RNS.PacketReceipt.SENT``, ``RNS.PacketReceipt.DELIVERED``, ``RNS.PacketReceipt.FAILED`` or ``RNS.PacketReceipt.CULLED``.
+ """
+ return self.status
+
# Validate a proof packet
def validate_proof_packet(self, proof_packet):
if hasattr(proof_packet, "link") and proof_packet.link:
@@ -374,6 +407,9 @@ class PacketReceipt:
return False
def rtt(self):
+ """
+ :returns: The round-trip-time in seconds
+ """
return self.concluded_at - self.sent_at
def is_timed_out(self):
@@ -395,18 +431,30 @@ class PacketReceipt:
#self.callbacks.timeout(self)
- # Set the timeout in seconds
def set_timeout(self, timeout):
+ """
+ Sets a timeout in seconds
+
+ :param timeout: The timeout in seconds.
+ """
self.timeout = float(timeout)
- # Set a function that gets called when
- # a successfull delivery has been proved
def delivery_callback(self, callback):
+ """
+ Sets a function that gets called if a successfull delivery has been proven.
+
+ :param callback: A *callable* with the signature *callback(packet_receipt)*
+ """
self.callbacks.delivery = callback
# Set a function that gets called if the
# delivery times out
def timeout_callback(self, callback):
+ """
+ Sets a function that gets called if the delivery times out.
+
+ :param callback: A *callable* with the signature *callback(packet_receipt)*
+ """
self.callbacks.timeout = callback
class PacketReceiptCallbacks:

diff --git a/RNS/Transport.py b/RNS/Transport.py
index 925af0d0f..8b8237265 100755
--- a/RNS/Transport.py
+++ b/RNS/Transport.py
@@ -318,7 +318,7 @@ class Transport:
Transport.jobs_locked = True
# TODO: This updateHash call might be redundant
- packet.updateHash()
+ packet.update_hash()
sent = False
# Check if we have a known path for the destination in the path table
@@ -907,12 +907,22 @@ class Transport:
@staticmethod
def register_announce_handler(handler):
+ """
+ Registers an announce handler.
+
+ :param handler: Must be an object with an *aspect_filter* attribute and a *received_announce(destination_hash, announced_identity, app_data)* callable. See the :ref:`Announce Example<example-announce>` for more info.
+ """
if hasattr(handler, "received_announce") and callable(handler.received_announce):
if hasattr(handler, "aspect_filter"):
Transport.announce_handlers.append(handler)
@staticmethod
def deregister_announce_handler(handler):
+ """
+ Deregisters an announce handler.
+
+ :param handler: The announce handler to be deregistered.
+ """
while handler in Transport.announce_handlers:
Transport.announce_handlers.remove(handler)
@@ -940,7 +950,7 @@ class Transport:
def cache(packet, force_cache=False):
if RNS.Transport.should_cache(packet) or force_cache:
try:
- packet_hash = RNS.hexrep(packet.getHash(), delimit=False)
+ packet_hash = RNS.hexrep(packet.get_hash(), delimit=False)
interface_reference = None
if packet.receiving_interface != None:
interface_reference = str(packet.receiving_interface)
@@ -1009,6 +1019,10 @@ class Transport:
@staticmethod
def has_path(destination_hash):
+ """
+ :param destination_hash: A destination hash as *bytes*.
+ :returns: *True* if a path to the destination is known, otherwise *False*.
+ """
if destination_hash in Transport.destination_table:
return True
else:
@@ -1016,6 +1030,13 @@ class Transport:
@staticmethod
def request_path(destination_hash):
+ """
+ Requests a path to the destination from the network. If
+ another reachable peer on the network knows a path, it
+ will announce it.
+
+ :param destination_hash: A destination hash as *bytes*.
+ """
path_request_data = destination_hash + RNS.Identity.get_random_hash()
path_request_dst = RNS.Destination(None, RNS.Destination.OUT, RNS.Destination.PLAIN, Transport.APP_NAME, "path", "request")
packet = RNS.Packet(path_request_dst, path_request_data, packet_type = RNS.Packet.DATA, transport_type = RNS.Transport.BROADCAST, header_type = RNS.Packet.HEADER_1)
@@ -1147,7 +1168,7 @@ class Transport:
hops = de[2]
expires = de[3]
random_blobs = de[4]
- packet_hash = de[6].getHash()
+ packet_hash = de[6].get_hash()
serialised_entry = [
destination_hash,

Served by rngit 1.5.1 - Generated in 0.19s